package com.aizuda.encrypt.util;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.aizuda.encrypt.constant.EncryptConstant;
import com.aizuda.encrypt.enums.EncryptType;
import com.aizuda.encrypt.helper.CryptoHelper;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 加密工具类
 *
 * @author nn200433
 * @date 2024-03-22 09:26:09
 */
@Slf4j
public class EncryptUtil {

    /**
     * 加密数据（一定带前缀）
     *
     * @param type      类型
     * @param key       密钥
     * @param str       要加密的数据
     * @param splitChar 按多少位分割
     * @return {@link String }
     * @author nn200433
     */
    public static String encrypt(EncryptType type, String key, String str, int splitChar) {
        final List<String> strList = splitChar(str, splitChar);
        return encrypt(type, key, Boolean.TRUE, strList.toArray(new String[]{}));
    }

    /**
     * 加密数据
     *
     * @param type       类型
     * @param key        密钥
     * @param str        要加密的数据
     * @param splitChar  按多少位分割
     * @param isAddIndex 是否加上真正数据的前缀
     * @return {@link String }
     * @author nn200433
     */
    public static String encrypt(EncryptType type, String key, String str, int splitChar, Boolean isAddIndex) {
        final List<String> strList = splitChar(str, splitChar);
        return encrypt(type, key, isAddIndex, strList.toArray(new String[]{}));
    }

    /**
     * 加密数据
     *
     * @param type       类型
     * @param key        密钥
     * @param isAddIndex 是否加上真正数据的前缀
     * @param strArray   要加密的数据组
     * @return {@link String }
     * @author nn200433
     */
    public static String encrypt(EncryptType type, String key, Boolean isAddIndex, String... strArray) {
        final SymmetricCrypto crypto     = CryptoHelper.cryptoHandler(type, key);
        StringBuffer          sb         = new StringBuffer();
        final int             arrayLen   = strArray.length;
        final int             endIndex   = arrayLen - 1;
        long                  beginIndex = 0;
        for (int i = 0; i < arrayLen; i++) {
            final String str        = strArray[i];
            final String encryptHex = crypto.encryptHex(str);
            final int    length     = encryptHex.length();
            if (i < endIndex) {
                beginIndex += length;
            }
            log.debug("---> [数据加密] {} | {} | {}", str, encryptHex, length);
            sb.append(encryptHex);
        }
        final String prefix = isAddIndex ? getPrefix(beginIndex) : StrUtil.EMPTY;
        return trans(prefix + sb);
    }

    /**
     * 分割字符串
     *
     * @param str   str
     * @param split 分裂
     * @return {@link List }<{@link String }>
     * @author nn200433
     */
    public static List<String> splitChar(String str, int split) {
        Assert.notBlank(str, "待处理的字符串不能为空...");
        List<String> rList  = new ArrayList<String>();
        final int    length = str.length();
        if (length <= split) {
            return Collections.singletonList(str);
        }
        for (int i = 0; i < length; i++) {
            final int end = i + split;
            if (end > length) {
                rList.add(str);
                break;
            }
            final String sub = str.substring(i, end);
            rList.add(sub);
        }
        return rList;
    }

    /**
     * 翻译成 “与佛论禅”、....
     *
     * @param str 译文
     * @return {@link String }
     * @author nn200433
     */
    public static String trans(String str) {
        return CryptoHelper.transTable().translate(str);
    }

    /**
     * 获取前缀
     *
     * @param beginIndex 开始索引
     * @return {@link String }
     * @author nn200433
     */
    private static String getPrefix(long beginIndex) {
        return StrUtil.padPre(HexUtil.toHex(beginIndex), EncryptConstant.PAD_PRE_COUNT, '0');
    }

}
